/*
	Copyright (C) 2011 Daniel C. Dennison (dandennison84@gmail.com).  All rights reserved.
	This file is licensed under the EPL 1.0 (Eclipse Public License 1.0)
	A copy of the license can be found at http://www.eclipse.org/legal/epl-v10.html
*/

package com.gmail.dandennison84.accounting

class JournalHelper {
	double getRetainedEarnings(Map<String, List<Account>> re, Date from = null, Date to = null) {
		re['equityAccounts'].inject(0) {
			acc, it -> acc + (it.getCreditBalanceBetween(from, to) - it.getDebitBalanceBetween(from, to))
		}
	}

	double getNetIncome(Map<String, List<Account>> is, Date from = null, Date to = null) {
		double totalOperatingRevenue = is['operatingRevenue'].inject(0) {
			acc, it -> acc + (it.getCreditBalanceBetween(from, to) - it.getDebitBalanceBetween(from, to))
		}
		double totalNonOperatingRevenue = is['nonOperatingRevenue'].inject(0) {
			acc, it -> acc + (it.getCreditBalanceBetween(from, to) - it.getDebitBalanceBetween(from, to))
		}
		double totalOperatingExpenses = is['operatingExpenses'].inject(0) {
			acc, it -> acc + (it.getDebitBalanceBetween(from, to) - it.getCreditBalanceBetween(from, to))
		}
		double totalNonOperatingExpenses = is['nonOperatingExpenses'].inject(0) {
			acc, it -> acc + (it.getDebitBalanceBetween(from, to) - it.getCreditBalanceBetween(from, to))
		}

		assert 50 == totalOperatingRevenue
		assert 10 == totalNonOperatingRevenue
		assert 50 == totalOperatingExpenses
		assert 0 == totalNonOperatingExpenses

		(totalOperatingRevenue + totalNonOperatingRevenue) - (totalOperatingExpenses - totalNonOperatingExpenses)
	}


	Map<String, List<Account>> getIncomeStatement(List<Account> coa) {
		postJournalEntries(coa)
		StatementBuilder isb = new StatementBuilder(coa)
		isb.incomeStatement {
			operatingRevenue(accountGroup:'operatingRevenue')
			nonOperatingRevenue(accountGroup:'nonOperatingRevenue')
			operatingExpenses(accountGroup:'operatingExpenses')
			nonOperatingExpenses(accountGroup:'nonOperatingExpenses')
		}
		isb.accounts
	}

	private void postJournalEntries(List<Account> coa) {
		Account sales = findAccount(coa, 'Freight Revenues')
		Account cos = findAccount(coa, 'Cost of Sales')
		Account interestIncome = findAccount(coa, 'Interest Income')
		Account advertising = findAccount(coa, 'Advertising Expense')
		Account cash = findAccount(coa, 'Cash')
		Account investments = findAccount(coa, 'Investments')
		Account inventory = findAccount(coa, 'Inventory')
		Account shortTermLiabilities = findAccount(coa, 'Accounts Payable')
		Account ownersEquity = findAccount(coa, 'Common Stock')

		Date today = new Date()
		Date yesterday = today - 1
		Date dayBeforeYesterday = yesterday - 1

		JournalEntry je = new JournalEntry(id:1, description:'opening balance', dateTime:dayBeforeYesterday)
		JournalEntryAmount debit1 = new JournalEntryAmount(account:cash, amount:1000)
		JournalEntryAmount credit1 = new JournalEntryAmount(account:ownersEquity, amount:1000)
		je.debits << debit1
		je.credits << credit1
		je.post()

		je = new JournalEntry(id:2, description:'initial inventory', dateTime:dayBeforeYesterday)
		credit1 = new JournalEntryAmount(account:cash, amount:500)
		debit1 = new JournalEntryAmount(account:inventory, amount:500)
		credit1.properties['items'] = 100
		je.debits << debit1
		je.credits << credit1
		je.post()

		je = new JournalEntry(id:3, description:'bought investments', dateTime:dayBeforeYesterday)
		credit1 = new JournalEntryAmount(account:cash, amount:100)
		debit1 = new JournalEntryAmount(account:investments, amount:100)
		je.debits << debit1
		je.credits << credit1
		je.post()

		je = new JournalEntry(id:4, description:'ran advertising add', dateTime:dayBeforeYesterday)
		credit1 = new JournalEntryAmount(account:shortTermLiabilities, amount:50)
		debit1 = new JournalEntryAmount(account:advertising, amount:50)
		je.debits << debit1
		je.credits << credit1
		je.post()

		je = new JournalEntry(id:5, description:'made sales', dateTime:yesterday)
		credit1 = new JournalEntryAmount(account:sales, amount:100)
		credit1.properties['items'] = 10
		debit1 = new JournalEntryAmount(account:cash, amount:100)
		je.debits << debit1
		je.credits << credit1
		debit1 = new JournalEntryAmount(account:cos, amount:50)
		credit1 = new JournalEntryAmount(account:inventory, amount:50)
		credit1.properties['items'] = 10
		je.debits << debit1
		je.credits << credit1
		je.post()

		je = new JournalEntry(id:6, description:'interest income', dateTime:yesterday)
		credit1 = new JournalEntryAmount(account:interestIncome, amount:10)
		debit1 = new JournalEntryAmount(account:cash, amount:10)
		je.debits << debit1
		je.credits << credit1
		je.post()
	}

	private Account findAccount(List<Account> coa, String name) {
		coa.find {it.name == name}
	}
}
